package model;

import java.util.ArrayList;
import java.util.Iterator;
import model.Field.Directions;

/**
 * LevelInterpreter vertaald een LevelSpecificatie om in een level.
 * Een level is een ArrayList van Fields en parts.
 * 
 */
public class LevelInterpreter {
    
    private ArrayList<Field> level;
    private final int FIELDSIZE = 30;
    
    public enum Parts {
        BOX, PLAYER, WALL, TERRAIN, ENEMY, EMPTY
    }

    public LevelInterpreter() {
       this.level = new ArrayList<>();
    }

    /*
     * Deze methode vertaald een LevelSpecificatie over in een level.
     * Invoer : een LevelSpecificatie.
     * Uitvoer: een level.
     * Een level is een ArrayList van Field en Part klassen waar voor elk Field
     * de x en y coordinate zijn gezet en de buren zijn bepaald en waar elk Part in het juiste Field is gezet.
     * interpreterLevel maakt gebruik van pair fields.
     */
    public ArrayList<Field> interpreterLevel(LevelSpecification levelSpecification) {
        
        int[][] fieldSpecification = levelSpecification.getFieldSpecification();

        for (int row = 0; row < fieldSpecification.length; row++) {

            for (int column = 0; column < fieldSpecification[row].length; column++) {

                int xCoordinate = column * FIELDSIZE;
                int yCoordinate = row * FIELDSIZE;

                Field field = new Field(xCoordinate, yCoordinate, levelSpecification.getImage(Parts.TERRAIN));

                switch (fieldSpecification[row][column]) {
                    case 0:
                        break;
                    case 1:
                        this.level.add(field);
                        break;
                    case 2:
                        field.setPart(new Wall(levelSpecification.getImage(Parts.WALL)));
                        field.getPart().setCurrentField(field);
                        this.level.add(field);
                        break;
                    case 3:
                        field.setPart(new Box(levelSpecification.getImage(Parts.BOX)));
                        field.getPart().setCurrentField(field);
                        this.level.add(field);
                        break;
                    case 4:
                        field.setPart(new Enemy(levelSpecification.getImage(Parts.ENEMY)));
                        field.getPart().setCurrentField(field);
                        this.level.add(field);
                        break;
                    case 5:
                        field.setPart(new Player(levelSpecification.getImage(Parts.PLAYER)));
                        field.getPart().setCurrentField(field);
                        this.level.add(field);
                        break;
                }
            }
        }

        this.pairFields();
        return level;
    }

    /*
     * Koppelt buren aan elkaar aan de hand van x en y coordinaten 
     */
    private void pairFields() {
        Iterator<Field> it = this.level.iterator();
        while (it.hasNext()) {
            Field f = it.next();
            for (int i = 0; i < 4; i++) {
                switch (i) {
                    case 0:
                        f.setNeighbor(findField((f.getxCoordinate() + FIELDSIZE), f.getyCoordinate()), Directions.RIGHT);
                        break;
                    case 1:
                        f.setNeighbor(findField((f.getxCoordinate() - FIELDSIZE), f.getyCoordinate()), Directions.LEFT);
                        break;
                    case 2:
                        f.setNeighbor(findField(f.getxCoordinate(), (f.getyCoordinate() + FIELDSIZE)), Directions.DOWN);
                        break;
                    case 3:
                        f.setNeighbor(findField(f.getxCoordinate(), (f.getyCoordinate() - FIELDSIZE)), Directions.UP);
                        break;
                }
            }
        }

    }

    /*
     * Vind een veld aan de hand van x en y coordinate
     */
    private Field findField(int xCoordinate, int yCoordinate) {

        Iterator<Field> it = this.level.iterator();
        while (it.hasNext()) {
            Field f = it.next();
            if (f.getxCoordinate() == xCoordinate && f.getyCoordinate() == yCoordinate) {
                return f;
            }
        }
        return null;
    }
}
